import org.apache.poi.hslf.extractor.PowerPointExtractor;
import org.apache.poi.hwpf.extractor.WordExtractor;
import org.apache.poi.hslf.HSLFSlideShow;
import org.apache.poi.hslf.usermodel.SlideShow;
import org.apache.poi.hpsf.*;
import org.apache.poi.hssf.extractor.ExcelExtractor;
import org.apache.poi.POIOLE2TextExtractor;
import org.apache.poi.hpsf.PropertySetFactory;
import org.apache.poi.hpsf.SummaryInformation; 
import org.apache.poi.*;
import org.apache.poi.poifs.eventfilesystem.*;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.*;
import java.io.*;
import java.util.Hashtable;
import java.util.Date;
import java.util.Enumeration;
import org.apache.poi.hssf.usermodel.*;


/*  Compile into jar: jar cmf meta-inf/manifest.mf
  fileread.jar fileread.class org/ */
/* Quick command line text extractor - based on Apache's POI etc. - e.tonkin@ukoln.ac.uk */

/* Call with java xslread filename.xsl ; options -metadata -text; default returns both */

public class fileread  implements POIFSReaderListener{

	static final int WORD=0;
	static final int POWERPOINT=1;
	static final int EXCEL=2;
	static final String[] typeString={"application/msword","application/mspowerpoint","application/msexcel"};

	static FileInputStream fstream;
	static Hashtable the_metadata;
	boolean returnmetadata=false;
	boolean returntext=false;
	
	public String readAsXLS(String fileName){
		try{
			fstream= new FileInputStream(fileName);
			HSSFWorkbook wb = new HSSFWorkbook(new POIFSFileSystem(fstream));
			ExcelExtractor extractor = new ExcelExtractor(wb);
			extractor.setFormulasNotResults(true);
			extractor.setIncludeSheetNames(false);
			POITextExtractor metadataextractor = extractor.getMetadataTextExtractor();
			// contains the actual text in the doc, sans formatting
			String thetext=extractor.getText();
			fstream.close();
			return thetext;
		} catch (java.lang.NullPointerException e){
			return null;	
		
		}catch (Exception e){
			return null;
		}
		
	}

	public String readAsPPT(String fileName){
		try{
                        fstream= new FileInputStream(fileName);
                        HSLFSlideShow test=new HSLFSlideShow(fstream);
                        SlideShow theShow=new SlideShow(test);
                        theShow.getSlides();
                        PowerPointExtractor extract=new PowerPointExtractor(fileName);
                        POITextExtractor metadataextractor = extract.getMetadataTextExtractor();
                        String thetext=extract.getText();
                        fstream.close();
			return thetext;
		} catch (java.lang.NullPointerException e){
			return null;	
		}catch (Exception e){
			return null;
		}
	}

	public String readAsDOC(String fileName){
                try {
                        fstream= new FileInputStream(fileName);
                        WordExtractor extract=new WordExtractor(fstream);
                        POITextExtractor metadataextractor = extract.getMetadataTextExtractor();
                        // contains the actual text in the doc, sans formatting
                        String thetext=extract.getText();
                        fstream.close();
			return thetext;
		} catch (java.lang.NullPointerException e){
			return null;	
		}catch (Exception e){
			return null;
		}
	}

	public static void main (String args[]){
		try {
			fileread reader=new fileread();
			int fileType=reader.whichMSOfficeApp(args[0]);
			if(fileType<1){ // turns out it simply isn't an office file
				System.err.println(args[0] + " is not an MS office file");
				System.exit(1);
			}
			
			String output=reader.readAsDOC(args[0]);
			fileType=WORD;
			if(output==null){
				output=reader.readAsXLS(args[0]);
				fileType=EXCEL;
			}
			if(output==null){
				output=reader.readAsPPT(args[0]);
				fileType=POWERPOINT;
			}
			if(output==null){
				System.err.println("Can't read file");
				System.exit(1);
			}
	
			fstream=new FileInputStream(args[0]);
			InputStream istream=(InputStream)fstream;
			// a second try     POIFSReader r = new POIFSReader();
			 POIFSReader r = new POIFSReader();
			 r.registerListener(new fileread(),
					                        "\005SummaryInformation");
			 r.read(istream);
			istream.close();
			
			if(the_metadata!=null){
			Enumeration e = the_metadata.keys();
         		while(e.hasMoreElements()) {
				String key = (String)(e.nextElement());
             			String value = (String)the_metadata.get(key);
				System.out.println(key+": \""+value+"\"");	
			}
			System.out.println("mimetype: "+typeString[fileType]);
			}
			System.out.println("---TEXT---");
			System.out.println(output);
			
		} catch (java.lang.NullPointerException e){
			System.err.println("Null pointer exception: "+e);

		} catch (Exception e){
			System.err.println("File input error "+e);
		}
	}
	
    public int whichMSOfficeApp(String fileName){
	try{
		fstream=new FileInputStream(fileName);
		int bytesRead=0;
		int bytesToRead=1024;
		byte[] input = new byte[bytesToRead];
		while (bytesRead < bytesToRead) {
			int result = fstream.read(input, bytesRead, bytesToRead - bytesRead);
			if (result == -1) break;
			bytesRead += result;
		}
		// For MS Office apps, should be: D0 CF 11 E0 A1 B1 1A E1
		String msOfficeID="ffffffd0 ffffffcf 11 ffffffe0 ffffffa1 ffffffb1 1a ffffffe1 ";
		String output="";
		for(int i=0;i<8;i++){
			output=output+Integer.toHexString(input[i])+" ";
		}
		if(output.equals(msOfficeID)){
			System.err.println(fileName+" is an MS office file");
			//String wordstring="ffffffec ffffffa5 ffffffc1 0 ";
			// Not much point in trying these; the magic number isn't stable

		/*	for(int i=512;i<516;i++){
				System.out.print(Integer.toHexString(input[i])+" ");	
				// 512 byte offset:
				// Doc: EC A5 C1 00
				// xls: FD FF FF FF nn 02 (or nn 00)
				// ppt: FD FF FF FF nn 00 00 00
			}
			System.out.println();*/
			return 1;
		} else {
			return -1;
		}
	} catch (java.lang.NullPointerException e){
		return -1;
	} catch (Exception e){
		return -1;		
	}
    }

    public void processPOIFSReaderEvent(POIFSReaderEvent event)
    {
	    
        SummaryInformation si = null;
	the_metadata=new Hashtable();
        try
        {
            si = (SummaryInformation)
                 PropertySetFactory.create(event.getStream());
        }
        catch (Exception ex)
        {
            throw new RuntimeException
                ("Property set stream \"" +
                 event.getPath() + event.getName() + "\": " + ex);
        }
        final String title = si.getTitle();
        if (title != null) {
            //System.out.println("Title: \"" + title + "\"");
	    the_metadata.put("Title",title);
        } else {
            //System.out.println("Document has no title.");
		the_metadata.put("Title","");
	}
	final String author=si.getAuthor();
	if(author != null) {
		//System.out.println("Author: \""+author+"\"");
	    the_metadata.put("Author",author);
	} else {
		//System.out.println("Document has no author.");
	    the_metadata.put("Author","");
	}
	final String lastauthor=si.getLastAuthor();
	if(lastauthor != null) {
		//System.out.println("LastAuthor: \""+lastauthor+"\"");
	    the_metadata.put("lastAuthor",lastauthor);
	} else { 
		//System.out.println("Document has no last author.");
	    the_metadata.put("lastAuthor","");
	}

	final String wordcount=Integer.toString(si.getWordCount());
	if(wordcount != null) {
		//System.out.println("Wordcount: \""+wordcount+"\"");
	    the_metadata.put("WordCount",wordcount);
	} else{ 
		//System.out.println("Document has no provided wordcount.");
		the_metadata.put("WordCount","");
	}
	final int int_pagecount=si.getPageCount();
	if(int_pagecount>-1) {
		//System.out.println("PageCount: \""+Integer.toString(int_pagecount)+"\"");
	    the_metadata.put("PageCount",Integer.toString(int_pagecount));
	} else  {
		//System.out.println("Document has no provided pagecount.");
		the_metadata.put("PageCount","");
	}
	final Date date_creationdatetime=si.getCreateDateTime();
	if(date_creationdatetime != null) {
		//System.out.println("CreateDateTime: \""+date_creationdatetime.toString()+"\"");
	    the_metadata.put("CreateDateTime",date_creationdatetime.toString());
	} else {
		//System.out.println("Document has no provided pagecount.");
		the_metadata.put("CreateDateTime","");
	}
    }

}	



